package qgs.zisu.javaconcurrency.javaconcurrency.chapter9_ThreadCommunication;

import java.util.*;

/**
 * @Author: 蔡翔
 * @Date: 2019/10/17 21:50
 * @Version 1.0  重要（模拟开固定的5个线程去 抓取20组数据，等全部抓取好后再做，后续操作）
 * 目的：开很多线程去采集多数据，但又为了防止cpu频繁上下文切换，所以就一次只能跑5个线程
 * 实现：为了实现要在所有线程 的开始和 结束加一把锁，而这里的锁就是    执行队列 《==》 LinkList（巧妙）
 */
public class CaptureService {

    final static private LinkedList<Control> CONTROLS = new LinkedList<>();
    private final static int MAX_WORKER = 5;

    public static void main(String[] args) {
        List<Thread> list = new ArrayList<>();
        Arrays.asList("M1","M2","M3","M4","M5","M6","M7","M8","M9","M10","M11").stream()
        .map(CaptureService::createCaptureThread)  //s -> createCaptureThread(s)可以写成CaptureService::createCaptureThread
        .forEach(t->{
            t.start();
            list.add(t);
        }); //返回t.start()；；t->t.start() 和 t->{t.start()} 是一样的。

        //先start()所有线程，再join所有线程。也就是这11个线程同时启动。
        list.stream().forEach(t-> {
            try {
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        Optional.of("All of capture work finished").ifPresent(System.out::println);
    }
    private static Thread createCaptureThread(String name){
        //()->{}  左边代表0个参数（因为Runnable 执行的是run方法），右边代表什么也不做
        /*
        就类似于
        return (new Runnable(){
　　          @Override
　　          public void run(){
　　          }
        });
        */
        return new Thread(()->{
            //Optional.of().ifPresent() 可以防止空指针异常。如果of里面的东西存在，就会执行ifPresent()里面的内容。
            Optional.of("The worker ["+Thread.currentThread().getName()+"] begin capture data")
                    .ifPresent(System.out::println);
            //这里定义了一个LinkList的锁 很巧妙。（重点）
            synchronized (CONTROLS){
                while (CONTROLS.size()>MAX_WORKER){
                    try {
                        //当 当前线程阻塞在这里的时候，别人唤醒我我回去在循环一次看看是否 当前线程小于5
                        CONTROLS.wait();
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
                CONTROLS.addLast(new Control());
            }
            Optional.of("The worker ["+Thread.currentThread().getName()+"] is working...")
                    .ifPresent(System.out::println);
            try {
                //模拟抓取数据的 时间 。。。
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (CONTROLS){
                //如果Optional.of() 没有 ifPresent() 那就输出不了。
                Optional.of("The worker ["+Thread.currentThread().getName()+"] is END capture data.")
                .ifPresent(System.out::println);
                CONTROLS.removeFirst();  //先进先出
                //CONTROLS.notifyAll(); 是指唤醒所有以CONTROLS为锁 并且已近锁住的代码
                CONTROLS.notifyAll();

            }
        },name);
    }

    //类也可以加static（就变成了静态类）
    private static class Control{

    }
}
